----------Submarine Commander----------
A 4am crack                  2018-03-17
---------------------------------------

Name: Submarine Commander
Genre: simulation
Year: 1983
Credits: Patrick Buckland
Publisher: Thorn EMI Video
Platform: Apple ][+ or later
Media: 5.25-inch disk
Sides: 1
OS: Diversi-DOS C1982
Similar cracks:
  #599 Word Man

                   ~

               Chapter 0
 In Which Various Automated Tools Fail
          In Interesting Ways


COPYA
  disk read error on first pass

Locksmith Fast Disk Backup
  can't read T02,S09 or anything after
  track $02

EDD 4 bit copy (no sync, no count)
  no errors during copying
  copy loads a few tracks then grinds
    and crashes

Copy ][+ nibble editor
  T03 appears unformatted ("HI-RES DISK
    SCAN" confirms this)
  T04+ use modified data epilogue
    (DF AA EB)

Disk Fixer
  T00 -> looks like a DOS 3.3 RWTS
  T00-T02 -> looks like a full DOS
  T01,S09 -> startup program is "HELLO"
  ["O" -> "Input/Output Control"]
    set Data Epilogue to "DF AA EB"
  T04+ readable, but slightly garbage
  (possibly a modified nibble translate
  table?)

Why didn't COPYA work?
  T03 unformatted, modified epilogue
  bytes (T04+)

Why didn't Locksmith FDB work?
  ditto

Why didn't my EDD copy work?
  probably a nibble check during boot

Why do the sectors look like garbage
even after changing the data epilogue?
  probably some changes to the nibble
  translate table (possibly tied to the
  protection check)

Next steps:

  1. trace the boot to find the
     protection check and RWTS changes
  2. capture the final RWTS and use it
     to convert the rest of the disk
  3. ???

                   ~

               Chapter 1
In Which Automated Tools Get Us Nowhere


[S6,D1=original disk]
[S6,D2=blank disk]
[S5,D1=my work disk]

]PR#5
...
CAPTURING BOOT0
...reboots slot 6...
...reboots slot 5...
SAVING BOOT0
CAPTURING BOOT1
...reboots slot 6...
...reboots slot 5...
SAVING BOOT1
SAVING RWTS

]BRUN ADVANCED DEMUFFIN 1.5

["5" to switch to slot 5]

["R" to load a new RWTS module]
  --> At $B8, load "RWTS" from drive 1

["6" to switch to slot 6]

["C" to convert disk]

                 --v--

ADVANCED DEMUFFIN 1.5    (C) 1983, 2014
ORIGINAL BY THE STACK    UPDATES BY 4AM
=======PRESS ANY KEY TO CONTINUE=======
TRK:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
+.5:
    0123456789ABCDEF0123456789ABCDEF012
SC0:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SC1:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SC2:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SC3:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SC4:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SC5:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SC6:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SC7:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SC8:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SC9:..RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SCA:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SCB:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SCC:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SCD:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SCE:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
SCF:...RRRRRRRRRRRRRRRRRRRRRRRRRRRRRRRR
=======================================
16SC $00,$00-$22,$0F BY1.0 S6,D1->S6,D2

                 --^--

Well then. That was... not entirely
successful. Not entirely unsuccessful,
I suppose. But I need to dig deeper.

                   ~

               Chapter 2
  In Which We Find Something Curious
  And Our Adventure Begins In Earnest


]PR#5
...
]CALL -151

*9600<C600.C6FFM

; set up callback #1 after boot0 loads
; boot1
96F8-   A9 4C       LDA   #$4C
96FA-   8D 4A 08    STA   $084A
96FD-   A9 0A       LDA   #$0A
96FF-   8D 4B 08    STA   $084B
9702-   A9 97       LDA   #$97
9704-   8D 4C 08    STA   $084C

; start the boot
9707-   4C 01 08    JMP   $0801

; (callback #1) set up callback #2
; after boot1 loads boot2
970A-   A9 4C       LDA   #$4C
970C-   8D 47 B7    STA   $B747
970F-   A9 1C       LDA   #$1C
9711-   8D 48 B7    STA   $B748
9714-   A9 97       LDA   #$97
9716-   8D 49 B7    STA   $B749

; continue the boot
9719-   4C 00 B7    JMP   $B700

; (callback #2) copy entire DOS into
; lower memory so it survives a reboot
; to my work disk
971C-   A2 23       LDX   #$23
971E-   A0 00       LDY   #$00
9720-   B9 00 9D    LDA   $9D00,Y
9723-   99 00 1D    STA   $1D00,Y
9726-   C8          INY
9727-   D0 F7       BNE   $9720
9729-   EE 22 97    INC   $9722
972C-   EE 25 97    INC   $9725
972F-   CA          DEX
9730-   D0 EE       BNE   $9720

; and reboot to my work disk
9732-   4C 00 C5    JMP   $C500

*BSAVE TRACE,A$9600,L$135
*9600G
...reboots slot 6...
...reboots slot 5...

]BSAVE OBJ.9D00-BFFF,A$1D00,L$2300
]CALL -151

*FE89G FE93G      ; disconnect real DOS
*9D00<1D00.3FFF   ; move DOS into place

*9D84L
.
. nothing unusual, until...
.
9E4D-   4C 8E AE    JMP   $AE8E

That is supposed to jump to $A180. And
$AE8E is supposed to be part of the
INIT routine. I certainly hope we're
not formatting the disk.

*AE8EL

AE8E-   AC 96 BA    LDY   $BA96
AE91-   F0 01       BEQ   $AE94
AE93-   20 C8 8C    JSR   $8CC8   <-- ?
AE96-   9A          TXS
AE97-   BA          TSX

Wait, what?

Oh, wait, I see it. $BA96 is always 0,
so the BEQ at $AE91 always branches
to... the middle of the next listed
instruction. Just to make it slightly
more difficult to do exactly the thing
I am trying to do, 35 years later. A
little "f--- you" from 1983.

*AE93:EA
*AE8EL

AE8E-   AC 96 BA    LDY   $BA96
AE91-   F0 01       BEQ   $AE94
AE93-   EA          NOP
AE94-   C8          INY
AE95-   8C 9A BA    STY   $BA9A
AE98-   C8          INY
AE99-   D0 01       BNE   $AE9C   <-- !
AE9B-   4C 8C 97    JMP   $978C  (fake)

And again.

*AE9B:EA
*AE99L

AE99-   D0 01       BNE   $AE9C
AE9B-   EA          NOP
AE9C-   8C 97 BA    STY   $BA97
AE9F-   AC 29 BA    LDY   $BA29
AEA2-   D0 01       BNE   $AEA5
AEA4-   6C C8 8C    JMP   ($8CC8)
AEA7-   2B          ???
AEA8-   BA          TSX

And on and on.

*AEA4:EA
*AEAB:EA
*AEB1:EA
*AEC1:EA
*AECC:EA
*AED4:EA
*AEDC:EA

*AE8EL

; fiddling with nibble translation
; tables (both read and write), which
; explains why the sectors in higher
; tracks appeared "garbled"
AE8E-   AC 96 BA    LDY   $BA96
AE91-   F0 01       BEQ   $AE94
AE93-   EA          NOP
AE94-   C8          INY
AE95-   8C 9A BA    STY   $BA9A
AE98-   C8          INY
AE99-   D0 01       BNE   $AE9C
AE9B-   EA          NOP
AE9C-   8C 97 BA    STY   $BA97
AE9F-   AC 29 BA    LDY   $BA29
AEA2-   D0 01       BNE   $AEA5
AEA4-   EA          NOP
AEA5-   C8          INY
AEA6-   8C 2B BA    STY   $BA2B
AEA9-   D0 01       BNE   $AEAC
AEAB-   EA          NOP
AEAC-   C8          INY
AEAD-   C8          INY
AEAE-   C8          INY
AEAF-   D0 01       BNE   $AEB2
AEB1-   EA          NOP
AEB2-   8C 2A BA    STY   $BA2A

; set up RWTS parameter table --
; track $02
AEB5-   A0 02       LDY   #$02
AEB7-   8C EC B7    STY   $B7EC
AEBA-   88          DEY

; read command ($01)
AEBB-   8C F4 B7    STY   $B7F4
AEBE-   88          DEY
AEBF-   F0 01       BEQ   $AEC2
AEC1-   EA          NOP
AEC2-   8C F0 B7    STY   $B7F0
AEC5-   8C EB B7    STY   $B7EB

; sector $09 (the unreadable sector)
AEC8-   A2 09       LDX   #$09
AECA-   D0 01       BNE   $AECD
AECC-   EA          NOP
AECD-   8E ED B7    STX   $B7ED

; address $7900
AED0-   A9 79       LDA   #$79
AED2-   D0 01       BNE   $AED5
AED4-   EA          NOP
AED5-   8D F1 B7    STA   $B7F1
AED8-   A9 B7       LDA   #$B7
AEDA-   D0 01       BNE   $AEDD
AEDC-   EA          NOP
AEDD-   A0 E8       LDY   #$E8

; read it
AEDF-   20 D9 03    JSR   $03D9

; and jump there
AEE2-   4C 02 79    JMP   $7902

And that's where I can interrupt the
boot, to capture the code at $7900.

On the bright side, at least we're not
formatting the disk.

                   ~

               Chapter 3
     In Which We Try To Understand
     Some Code That Someone Really
     Doesn't Want Us To Understand


*9600<C600.C6FFM

; set up callback #1 after boot0 loads
; boot1
96F8-   A9 4C       LDA   #$4C
96FA-   8D 4A 08    STA   $084A
96FD-   A9 0A       LDA   #$0A
96FF-   8D 4B 08    STA   $084B
9702-   A9 97       LDA   #$97
9704-   8D 4C 08    STA   $084C

; start the boot
9707-   4C 01 08    JMP   $0801

; (callback #1) set up callback #2
; after boot1 loads boot2
970A-   A9 4C       LDA   #$4C
970C-   8D 47 B7    STA   $B747
970F-   A9 1C       LDA   #$1C
9711-   8D 48 B7    STA   $B748
9714-   A9 97       LDA   #$97
9716-   8D 49 B7    STA   $B749

; continue the boot
9719-   4C 00 B7    JMP   $B700

; (callback #2) reboot to my work disk
; after boot2 loads the mystery code at
; $7900

971C-   A9 4C       LDA   #$4C
971E-   8D E2 AE    STA   $AEE2
9721-   A9 00       LDA   #$00
9723-   8D E3 AE    STA   $AEE3
9726-   A9 C5       LDA   #$C5
9728-   8D E4 AE    STA   $AEE4

; continue the boot
972B-   4C 84 9D    JMP   $9D84

*BSAVE TRACE2,A$9600,L$12E
*9600G
...reboots slot 6...
...reboots slot 5...

]BSAVE OBJ.7900-79FF,A$7900,L$100
]CALL -151

*7902L

7902-   EA          NOP
7903-   EA          NOP
7904-   EA          NOP
7905-   AE 5E BA    LDX   $BA5E
7908-   D0 01       BNE   $790B   <-- !
790A-   4C AD F4    JMP   $F4AD  (fake)
790D-   BA          TSX          (fake)

Oh look. More obfuscated code. It's
basically the same idea as the previous
routine -- the branch at $7908 is
unconditional, so execution continues
in the middle of the listed instruction
(at $790B).

*790A:EA

(There are a lot more of these.)

*792D:EA
*7935:EA
*794B:EA
*7956:EA
*795C:EA
*7961:EA
*796A:EA
*7970:EA

Seriously.

Here is the final, unobfuscated
disassembly:

*7902L

7902-   EA          NOP
7903-   EA          NOP
7904-   EA          NOP
7905-   AE 5E BA    LDX   $BA5E
7908-   D0 01       BNE   $790B
790A-   EA          NOP
790B-   AD F4 BA    LDA   $BAF4

; more nibble translation fiddling
790E-   8D F5 BA    STA   $BAF5
7911-   EE F4 BA    INC   $BAF4
7914-   8E 5F BA    STX   $BA5F
7917-   EE 5E BA    INC   $BA5E
791A-   EE 2E BA    INC   $BA2E
791D-   CE 2F BA    DEC   $BA2F
7920-   EE 9E BA    INC   $BA9E
7923-   CE 9F BA    DEC   $BA9F

; now set up an RWTS table --
; read command ($01)
7926-   A9 01       LDA   #$01
7928-   8D F4 B7    STA   $B7F4
792B-   D0 01       BNE   $792E
792D-   EA          NOP

; sector $0A
792E-   A9 0A       LDA   #$0A
7930-   8D ED B7    STA   $B7ED
7933-   D0 01       BNE   $7936
7935-   EA          NOP

; track $02
7936-   A9 02       LDA   #$02
7938-   8D EC B7    STA   $B7EC

; address $AE00 (?!?)
793B-   A9 AE       LDA   #$AE
793D-   8D F1 B7    STA   $B7F1

Oh, I see -- we're covering our tracks
by overwriting the previous caller with
real code. So a memory capture after
this point wouldn't show how we got
here or what modifications were done
in the previous step.

; call RWTS to read the real $AE00 and
; overwrite the protected one
7940-   A9 B7       LDA   #$B7
7942-   A0 E8       LDY   #$E8
7944-   20 B5 B7    JSR   $B7B5

; even more RWTS modifications
7947-   A9 DF       LDA   #$DF
7949-   D0 01       BNE   $794C
794B-   EA          NOP
794C-   8D 35 B9    STA   $B935
794F-   8D 9E B8    STA   $B89E
7952-   A0 FC       LDY   #$FC
7954-   D0 01       BNE   $7957
7956-   EA          NOP
7957-   8C 60 BC    STY   $BC60
795A-   D0 01       BNE   $795D
795C-   EA          NOP
795D-   A0 D7       LDY   #$D7
795F-   D0 01       BNE   $7962
7961-   EA          NOP
7962-   8C 7A BC    STY   $BC7A
7965-   8C 55 B9    STY   $B955
7968-   D0 01       BNE   $796B
796A-   EA          NOP
796B-   8C E7 B8    STY   $B8E7
796E-   D0 01       BNE   $7971
7970-   EA          NOP
7971-   8C 53 B8    STY   $B853

; another RWTS read, from T04,S00
7974-   A9 00       LDA   #$00
7976-   8D ED B7    STA   $B7ED
7979-   A0 04       LDY   #$04
797B-   8C EC B7    STY   $B7EC

; overwrite the call that started us
; down this path in the first place
797E-   A2 80       LDX   #$80
7980-   8E 4E 9E    STX   $9E4E
7983-   A2 A1       LDX   #$A1
7985-   8E 4F 9E    STX   $9E4F

; address $7900 -- so again, we're
; covering our tracks in memory
7988-   A9 79       LDA   #$79
798A-   8D F1 B7    STA   $B7F1
798D-   A9 00       LDA   #$00
798F-   8D EB B7    STA   $B7EB

; continue elsewhere
7992-   4C AF BE    JMP   $BEAF

*BEAFL

; execute the sector read (into $7900)
BEAF-   A9 B7       LDA   #$B7
BEB1-   A0 E8       LDY   #$E8
BEB3-   20 B5 B7    JSR   $B7B5

; set languard card so Applesoft is
; available (not shown)
BEB6-   A9 4C       LDA   #$4C
BEB8-   20 B2 A5    JSR   $A5B2
BEBB-   EA          NOP

; finally continue with the boot (but
; with the RWTS modifications in place)
BEBC-   4C 80 A1    JMP   $A180

And that's where my next interrupt will
be.

                   ~

               Chapter 4
       In Which We (Finally) Use
   The Original Disk Against Itself


*9600<C600.C6FFM

; set up callback #1 and start the boot
96F8-   A9 4C       LDA   #$4C
96FA-   8D 4A 08    STA   $084A
96FD-   A9 0A       LDA   #$0A
96FF-   8D 4B 08    STA   $084B
9702-   A9 97       LDA   #$97
9704-   8D 4C 08    STA   $084C
9707-   4C 01 08    JMP   $0801

; (callback #1) set up callback #2 and
; continue the boot
970A-   A9 4C       LDA   #$4C
970C-   8D 47 B7    STA   $B747
970F-   A9 1C       LDA   #$1C
9711-   8D 48 B7    STA   $B748
9714-   A9 97       LDA   #$97
9716-   8D 49 B7    STA   $B749
9719-   4C 00 B7    JMP   $B700

; (callback #2) set up callback #3 and
; continue the boot
971C-   A9 4C       LDA   #$4C
971E-   8D BC BE    STA   $BEBC
9721-   A9 2E       LDA   #$2E
9723-   8D BD BE    STA   $BEBD
9726-   A9 97       LDA   #$97
9728-   8D BE BE    STA   $BEBE
972B-   4C 84 9D    JMP   $9D84

; (callback #3) copy RWTS to lower
; memory so it survives a reboot
972E-   A2 08       LDX   #$08
9730-   A0 00       LDY   #$00
9732-   B9 00 B8    LDA   $B800,Y
9735-   99 00 38    STA   $3800,Y
9738-   C8          INY
9739-   D0 F7       BNE   $9732
973B-   EE 34 97    INC   $9734
973E-   EE 37 97    INC   $9737
9741-   CA          DEX
9742-   D0 EE       BNE   $9732

; and finally reboot to my work disk
9744-   4C 00 C5    JMP   $C500

*BSAVE TRACE3,A$9600,L$147
*9600G
...reboots slot 6...
...reboots slot 5...

]BSAVE RWTS,A$2800,L$800

]BRUN ADVANCED DEMUFFIN 1.5

["5" to switch to slot 5]

["R" to load a new RWTS module]
  --> At $B8, load "RWTS" from D1

["6" to switch to slot 6]

["C" to convert disk]

["Y" to change default values]

                 --v--

ADVANCED DEMUFFIN 1.5    (C) 1983, 2014
ORIGINAL BY THE STACK    UPDATES BY 4AM
=======================================


INPUT ALL VALUES IN HEX


SECTORS PER TRACK? (13/16) 16

START TRACK: $04        <-- change this
START SECTOR: $00
END TRACK: $22
END SECTOR: $0F

INCREMENT: 1

MAX # OF RETRIES: 0

COPY FROM DRIVE 1
TO DRIVE: 2
=======================================
16SC $04,$00-$22,$0F BY1.0 S6,D1->S6,D2

                 --^--

And here we go...

                 --v--

ADVANCED DEMUFFIN 1.5    (C) 1983, 2014
ORIGINAL BY THE STACK    UPDATES BY 4AM
=======PRESS ANY KEY TO CONTINUE=======
TRK:    ...............................
+.5:
    0123456789ABCDEF0123456789ABCDEF012
SC0:    ...............................
SC1:    ...............................
SC2:    ...............................
SC3:    ...............................
SC4:    ...............................
SC5:    ...............................
SC6:    ...............................
SC7:    ...............................
SC8:    ...............................
SC9:    ...............................
SCA:    ...............................
SCB:    ...............................
SCC:    ...............................
SCD:    ...............................
SCE:    ...............................
SCF:    ...............................
=======================================
16SC $04,$00-$22,$0F BY1.0 S6,D1->S6,D2

                 --^--

And there was much rejoicing.

]PR#5
]CATALOG,S6,D2

C1983 DSR^C#254
328 FREE

 A 002 HELLO
 B 034 DISP.MAP
 B 026 SUB.OBJ0
 B 034 SUB.OBJ1
 B 038 SCRUBS
 B 034 BANG

]RUN HELLO
...works...

The reason I always do this is to see
whether there are any runtime checks
for subtle differences in the original
DOS. If the program runs after booting
from a third-party disk, I can
eliminate a whole range of possible
secondary protections. Not only does
the game work after booting from my
work disk, it runs from drive 2 without
complaint.

Now to make the disk be able to read
itself (remember, it still has the
original RWTS on it)...

Going all the way back, the original
RWTS is capable of reading a standard
disk -- most of the first few tracks
were standard, before all the fiddling.
I can bypass all the fiddling by making
$9E4D jump to $A180 instead of $AE8E.

T00,S0D,$4E: 8EAE -> 80A1

]PR#6
...works, and it is glorious...

Quod erat liberandum.

                   ~

            Acknowledgments


Thanks to Ian Baronofsky for lending me
original disk.

---------------------------------------
A 4am crack                    No. 1722
------------------EOF------------------
